'''
This file is part of DopplerShift.

    DopplerShift is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DopplerShift is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DopplerShift.  If not, see <http://www.gnu.org/licenses/>.
'''
from dopplershift.core.exc import DSException
from dopplershift.core.containers.container import DSContainer
import logging
logger = logging.getLogger(__name__)
import traceback

class UnacceptebleEventsList(DSException):
    '''
    Unknown or not acceptable events list type
    '''
class UnknownEvent(DSException):
    '''
    Selectable event not signing on this event manager
    '''
class UncallableObject(DSException):
    '''
    Rised if signafication callback not callable
    '''

class EventCallbacksContainer(DSContainer):
    def __init__(self):
        self._listed_callbacks = []
        DSContainer.__init__(self)
    def set(self, obj):
        cnt = DSContainer.set(self, obj)
        self._listed_callbacks.append(obj)
        
    def call(self, event):
        if len(self._contained_object) < 1:
            return False
        for callback in self._listed_callbacks:
            try:
                callback(event)
            except:
                traceback.print_exc()
        return True

class DSEventManager:
    _accept_events = None
    events_container = EventCallbacksContainer
    def __init__(self, accept_events):
        if not isinstance(accept_events, list):
            raise UnacceptebleEventsList("")
        self._accept_events = {}
        for el in accept_events:
            self.accept_event(el)
    def sign(self, event_name, callback):
        if not callable(callback):
            raise UncallableObject(str(callback))
        if event_name not in self._accept_events:
            raise UnknownEvent(event_name)
        return self._accept_events[event_name].set(callback)
    def generate(self, event_name, arg_obj):
        logger.warning("Generate is deprecated method for DSEventManager")
        self.signal(event_name, arg_obj)
    def signal(self, event_name, arg_obj):
        logging.debug("Happen event <%s>"%event_name)
        if event_name not in self._accept_events:
            raise UnknownEvent(event_name)
        if not self._accept_events[event_name].call(arg_obj):
            logging.debug("Unsigned event <%s>"%(event_name))
    def accept_event(self, event_name):
        if event_name not in self._accept_events:
            self._accept_events[event_name] = EventCallbacksContainer()

